package ca.uvic.cs.cogz.reports;

import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.w3c.dom.Document;

import ca.uvic.cs.cogz.mapping.core.MappingTypeManager.MappingType;
import ca.uvic.cs.cogz.mapping.filter.TreeFilterManager;
import ca.uvic.cs.cogz.mapping.ontology.DataLoaderFacade;
import edu.stanford.smi.protege.model.Cls;
import edu.stanford.smi.protege.model.Frame;
import edu.stanford.smi.protege.model.KnowledgeBase;

public class MappingHierarchyReport extends AbstractReport {
	private int type;

	private KnowledgeBase kb;

	public MappingHierarchyReport() {}

	public MappingHierarchyReport(int type, KnowledgeBase kb) {
		this.type = type;
		this.kb = kb;
	}

	@Override
	public String getReportAsHTML() {
		StringBuilder reportHTML = new StringBuilder();
		reportHTML.append(getHTMLStart());

		reportHTML.append(getReportSummaryAsHTML());
		reportHTML.append(getReportContentsAsHTML());

		reportHTML.append(getHTMLEnd());

		return reportHTML.toString();
	}

	@Override
	public Document getReportAsXML() {
		//  Auto-generated method stub
		return null;
	}

	@Override
	public String getReportTitle() {
		if (type == TreeFilterManager.SOURCE_SEARCH) {
			return "Mapping Hierarchy Report - Source";
		} else {
			return "Mapping Hierarchy Report - Target";
		}
	}

	@SuppressWarnings("unchecked")
	private String getReportContentsAsHTML() {
		StringBuilder sbHtml = new StringBuilder();

		Set<Frame> validFrames = new HashSet<Frame>();

		Map<Frame, MappingType> frameToMappingType;
		if (type == TreeFilterManager.SOURCE_SEARCH) {
			frameToMappingType = DataLoaderFacade.getInstance().getMappingCollection().getSourceFrames();
		} else {
			frameToMappingType = DataLoaderFacade.getInstance().getMappingCollection().getTargetFrames();
		}

		for (Frame searchHit : frameToMappingType.keySet()) {
			MappingType frameMappingType = frameToMappingType.get(searchHit);
			if (frameMappingType.equals(MappingType.VERIFIED_MAPPING)) {
				validFrames.add(searchHit);
				if(searchHit instanceof Cls) {
					validFrames.addAll(((Cls) searchHit).getSuperclasses());
				}
			}
		}

		sbHtml.append("<div class=\"hiearchyTitle\">" + kb.getName() + " - mapped item hierarchy</div>");
		sbHtml.append("<ul>");
		sbHtml.append("<li>" + kb.getRootCls().getBrowserText() + "</li>");
		sbHtml.append(getHierarchy(kb.getRootCls(), validFrames, frameToMappingType));
		sbHtml.append("</ul>");

		return sbHtml.toString();
	}

	private String getHierarchy(Cls cls, Set<Frame> validFrames, Map<Frame, MappingType> frameToMappingType) {
		StringBuilder sbHtml = new StringBuilder();

		for (Object o : cls.getDirectSubclasses()) {
			if (validFrames.contains(o)) {
				Cls child = (Cls) o;
				MappingType mappingType = frameToMappingType.get(child);
				if (mappingType != null && mappingType.equals(MappingType.VERIFIED_MAPPING)) {
					sbHtml.append("<ul><li class=\"mappedItem\">" + child.getBrowserText() + "</li>");
				} else {
					sbHtml.append("<ul><li>" + child.getBrowserText() + "</li>");
				}
				sbHtml.append(getHierarchy(child, validFrames, frameToMappingType));
				sbHtml.append("</ul>");
			}
		}

		return sbHtml.toString();
	}

}
